module gui.gwindow;

import AGui.Backends.Allegro5.Allegro5;
import AGui.AGui;
import AGui.Widgets.Frame.FrameListener;

import share.container;
import mirshare, mirdefine;
import common.imagearray;

import allegro5.allegro;
import allegro5.allegro_image;


public class GWindow : Widget
{
    private int m_nFrameImgIdx;        // ÀÌ¹ÌÁö °ü·Ã º¯¼öµé. 

    private bool m_bFocused; 
    private bool m_bMoving;              // À©µµ¿ì ¿òÁ÷ÀÌ´ÂÁöÀÇ ¿©ºÎ.
    private bool m_bCanMove;             // À©µµ¿ì °íÁ¤¿©ºÎ.
    private bool _isCenter;
    private int _realWidth;
    private int _realHeight;

    private int dragX = 0;
    private int dragY = 0;
    
    private Vector!FrameListener frameListeners;

    private Allegro5Image _frame_img;
    private ImageArray m_images;


    protected override void paintComponent(PaintEvent paintEvent)
    {
        // Empty
    }
    
    protected override void paintBackground(PaintEvent paintEvent)
    {
        immutable int borderSize = 1;
        immutable int innerBorderTLX = getMargin(SideEnum.SIDE_LEFT) - borderSize;
        immutable int innerBorderTLY = getMargin(SideEnum.SIDE_TOP) - borderSize;
        immutable int innerBorderBRX = getWidth() - getMargin(SideEnum.SIDE_RIGHT) + borderSize;
        immutable int innerBorderBRY = getHeight() - getMargin(SideEnum.SIDE_BOTTOM) + borderSize;
        
        float opacity = (isMoving()) ? 0.9f : 0.85f;

        paintEvent.graphics().drawImage(_frame_img,
                                        IntPoint(innerBorderTLX, innerBorderTLY), opacity);
    }
    
    /**
     * Adds the parameter FrameListener.
     * @since 0.1.0
     */
    public void addFrameListener(FrameListener listener)
    {
        if (listener is null)
        {
            return;
        }
        
        if (frameListeners.contains(listener))
        {
            return;
        }
        
        frameListeners.add(listener);
    }
    
    /**
     * Removes the parameter FrameListener.
     * @since 0.1.0
     */
    public void removeFrameListener(FrameListener listener)
    {
        frameListeners.remove(listener);
    }
    
    /**
     * Adds the parameter widget to the frame itself (not the content pane).
     * @since 0.1.0
     */
    public void addToFrame(Widget widget)
    {
        super.add(widget);
    }
    
    /**
     * Removes the parameter widget from the frame itself (not the content pane).
     * @since 0.1.0
     */
    public void removeFromFrame(Widget widget)
    {
        super.remove(widget);
    }
    
    public override void mouseDown(ref MouseEvent mouseEvent)
    {
        immutable relativeMouse = IntPoint(mouseEvent.getX(), mouseEvent.getY());
        auto topRect = this.getInnerRectangle();
        //immutable Color pixel = _frame_img.getPixel(relativeMouse.getX(), relativeMouse.getY());
        //if (pixel.getA() == 0)
        //    return;

        bringToFront();
        
        mouseEvent.consume();

        if (isMovable())
        {
            if (topRect.pointInside(relativeMouse))
            {
                m_bMoving = true;
                dragX = mouseEvent.getX();
                dragY = mouseEvent.getY();
                
                return;
            }
        }

        m_bMoving = false;
    }
    
    public override void mouseDrag(ref MouseEvent mouseEvent)
    {
        if (m_bMoving)
        {
            int deltaX = mouseEvent.getX() - dragX + getLocation().getX();
            int deltaY = mouseEvent.getY() - dragY + getLocation().getY();
            
            setLocation(deltaX, deltaY);
            mouseEvent.consume();
        }
    }
    
    /**
     * Sets whether or not dragging the caption bar (top of the frame) will result in moving
     * the Frame.
     * @since 0.1.0
     */
    public void setMovable(bool move)
    {
        if (m_bCanMove != move)
        {
            foreach (FrameListener listener; frameListeners)
            {
                //if (listener !is null)
                //    listener.movableChanged(this, move);
            }
            
            m_bCanMove = move;
        }
    }
    
    /**
     * @return True if dragging the caption bar (top of the frame) will result in moving
     * the Frame.
     * @since 0.1.0
     */
    public bool isMovable() const
    {
        return m_bCanMove;
    }
    
    public override void mouseUp(ref MouseEvent mouseEvent)
    {
        if (m_bMoving)
        {
            mouseEvent.consume();
        }
        m_bMoving = false;
    }

    
    public int isMoving() const
    {
        return m_bMoving;
    }

    public void resetWindowImage(int nFrameImgIdx)
    {
        if (_frame_img !is null)
        {
            m_nFrameImgIdx = nFrameImgIdx;

            ALLEGRO_BITMAP* bmp, sub_bmp = null;

            bmp = m_images.GetCachedImage(m_nFrameImgIdx);
            if (bmp !is null)
            {
                if (_isCenter)
                {
                    int certerX = al_get_bitmap_width(bmp) / 2;
                    int certerY = al_get_bitmap_height(bmp) / 2;
                    int startX = certerX - (_realWidth / 2);
                    int startY = certerY - (_realHeight / 2);

                    //sub_bmp = al_create_sub_bitmap(bmp, m_nStartX, m_nStartY, _realWidth, _realHeight);
                    sub_bmp = al_create_sub_bitmap(bmp, startX, startY, _realWidth, _realHeight);
                    if (sub_bmp !is null)
                        _frame_img.setBitmap(sub_bmp, false);
                }
                else
                    _frame_img.setBitmap(bmp, false);
            }

            setSize(_frame_img.getWidth(), _frame_img.getHeight());
        }
    }

    public void setImages(ImageArray iarr)
    {
        m_images = iarr;
    }

    public void createWindow(ImageArray iarr, int nFrameImgIdx, bool canMove, bool isCenter = false, int width = 0, int height = 0)
    {
        m_images = iarr;
        m_nFrameImgIdx = nFrameImgIdx;
        m_bCanMove = canMove;
        _isCenter = isCenter;
        _realWidth = width;
        _realHeight = height;
        
        resetWindowImage(nFrameImgIdx);
    }

    public this()
    {
        super();

        _frame_img = new Allegro5Image();

        setFocusable(true);

        //setFrontColor(Color(240, 240, 240));
        //setBackColor(Color(196, 210, 224));

        setMargins(1, 1, 1, 1);
    }
    
    /**
     * Default destructor.
     * @since 0.1.0
     */
    public ~this()
    {
        foreach (FrameListener listener; frameListeners)
        {
            //if (listener !is null)
            //    listener.death(this);
        }

        if (_frame_img !is null)
        {
            delete _frame_img;
            _frame_img = null;
        }
    }
}